Skip to content

Comments

refactor: 뒤로가기 캐시 무효화 로직 작성#42

Merged
kangdy25 merged 2 commits intomainfrom
refactor/prevent-back-navigation
Feb 18, 2026
Merged

refactor: 뒤로가기 캐시 무효화 로직 작성#42
kangdy25 merged 2 commits intomainfrom
refactor/prevent-back-navigation

Conversation

@kangdy25
Copy link
Collaborator

@kangdy25 kangdy25 commented Feb 18, 2026

🚀 refactor: 뒤로가기 캐시 무효화 로직 작성

📝 변경사항

  • 뒤로가기 캐시 무효화 로직 작성
  • 소소한 코드 수정 (자간 수정, 종성에 따른 "이/가" 조건부 렌더링)

✅ 체크리스트

  • 코드 리뷰를 받았습니다
  • 테스트를 완료했습니다
  • 린터 에러가 없습니다
  • 타입 에러가 없습니다
  • 브라우저에서 테스트를 완료했습니다
  • 모바일에서 테스트를 완료했습니다 (해당되는 경우)

📸 스크린샷

UI 변경 사항이 있다면 이미지를 드래그해서 넣어주세요!

💬 리뷰어 전달사항

  • 리뷰어가 특별히 확인해야 할 사항이 있다면 적어주세요.

Summary by CodeRabbit

릴리스 노트

  • 버그 수정

    • 관련 캐시를 컴포넌트 마운트/언마운트 시 안정적으로 정리하여 데이터 일관성 개선
    • 뒤로가기/수정 시 이전 네비게이션 이슈 방지
  • 개선 사항

    • 검색 결과/상세 페이지에서 네비게이션 흐름을 교체해 예측 가능한 이동 동작 제공
    • 카테고리 문구 처리 개선으로 한국어 조사(이/가) 표기 정확도 향상
  • 스타일

    • 지도 인포 팝업 크기 조정 및 모달·UI 텍스트·포맷 정리

- 소소한 코드 수정 (자간 수정, 종성에 따른 "이/가" 조건부 렌더링)
@vercel
Copy link

vercel bot commented Feb 18, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
mingling-frontend Ready Ready Preview, Comment Feb 18, 2026 0:23am

@kangdy25 kangdy25 requested a review from kim3360 February 18, 2026 12:09
@coderabbitai
Copy link

coderabbitai bot commented Feb 18, 2026

Walkthrough

결과 페이지에서 중간지점/추천 쿼리 캐시를 무효화하는 로직과 이에 따른 네비게이션(flow)을 router.replace 기반으로 변경했고, 지도 출발지 정보 카드의 최소 너비 및 전송 모달의 스타일/클래스 정리를 함께 적용했습니다.

Changes

Cohort / File(s) Summary
결과 페이지 캐시·네비게이션
app/result/[id]/page.tsx
useCallback으로 clearRelatedCache 추가(중간지점/추천 쿼리 무효화). 마운트/언마운트 시 useEffect로 캐시 정리. 뒤로가기/수정 시작 흐름을 clearRelatedCache 호출 후 router.replace('/meeting/${id}')로 변경. getLineColor 대량 제거 및 관련 텍스트·포맷 소폭 조정.
지도 컴포넌트 레이아웃
components/map/kakaoMapLine.tsx
출발지 마커 정보 카드의 최소 너비를 min-w-[80px]min-w-20로 축소(레이아웃 변경).
모달 스타일 정리
components/modal/transferModal.tsx
Tailwind 클래스명·공백 재정렬, 문자열/이미지 경로 따옴표 통일, tracking 값 단위 조정 등 스타일/포맷 변경(기능 변화 없음).

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant ResultPage as ResultPage(Component)
    participant QueryClient as QueryClient(Cache)
    participant Router as Router

    User->>ResultPage: 클릭 (뒤로/수정 시작)
    ResultPage->>QueryClient: invalidateQueries('midpoint', id)
    ResultPage->>QueryClient: invalidateQueries('recommendation', id)
    ResultPage->>Router: router.replace("/meeting/{id}")
    Router-->>User: 네비게이션 완료
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • kim3360
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 변경사항의 주요 내용을 명확하게 요약하고 있으며, 캐시 무효화 로직 작성이라는 핵심 변경사항을 직접적으로 반영하고 있습니다.
Description check ✅ Passed PR 설명이 제공된 템플릿의 모든 필수 섹션(변경사항, 체크리스트)을 포함하고 있으며, 체크리스트의 모든 항목이 완료 표시되어 있습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/prevent-back-navigation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/result/[id]/page.tsx (1)

227-227: ⚠️ Potential issue | 🟠 Major

tracking-[-1.94%]는 유효하지 않은 CSS letter-spacing 값일 수 있습니다.

transferModal.tsx와 동일한 문제입니다. CSS letter-spacing 속성은 퍼센트 값을 지원하지 않으므로 브라우저에서 무시될 수 있습니다. px 또는 em 단위 사용을 권장합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/result/`[id]/page.tsx at line 227, Replace the invalid percentage-based
letter-spacing class tracking-[-1.94%] in the div with a valid unit-based
tracking value (e.g., tracking-[-1.94px] or tracking-[-0.02em]) so browsers
won't ignore it; update the className on the div in page.tsx (and mirror the
same change in transferModal.tsx where the same tracking-[-1.94%] is used) to
use Tailwind arbitrary unit syntax for letter-spacing with px or em units.
🧹 Nitpick comments (3)
app/result/[id]/page.tsx (3)

147-206: getLineColortransferModal.tsxgetLineBadgeStyle과 거의 동일합니다 — 공통 유틸로 추출을 권장합니다.

이 함수(~60줄)는 components/modal/transferModal.tsxgetLineBadgeStyle과 동일한 호선→색상 매핑 로직을 포함하고 있습니다. 새로운 노선이 추가되거나 색상이 변경될 때 두 곳을 모두 수정해야 하므로 유지보수 부담이 됩니다.

lib/ 또는 utils/ 디렉토리에 공통 함수로 추출하여 두 파일에서 import하는 것이 좋습니다.

#!/bin/bash
# 코드베이스 내 동일한 호선 색상 매핑 로직이 또 있는지 확인
rg -n "getLineColor\|getLineBadgeStyle\|bg-\[`#004A85`\]" --type=ts --type=tsx -g '!node_modules/**' | head -40
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/result/`[id]/page.tsx around lines 147 - 206, Extract the duplicate
subway line→color mapping into a shared utility (e.g., lib/lineColors.ts or
utils/lineColors.ts) and replace the local implementations: move the logic
currently in getLineColor (in page.tsx) and getLineBadgeStyle (in
components/modal/transferModal.tsx) into a single exported function (e.g.,
getLineColor or getLineBadgeStyle) and import it in both files; ensure the
function signature matches existing callers (accepting fullLineName string) and
keep the same return values (Tailwind bg- classes) so callers need only the
import change.

126-145: removeQueries 직후 같은 키에 invalidateQueries를 호출하는 것은 불필요합니다.

Line 128에서 removeQueries({ queryKey: ['midpoint', id] })로 쿼리를 캐시에서 완전히 제거한 후, Line 131에서 동일한 키로 invalidateQueries를 호출합니다. removeQueries는 쿼리 엔트리 자체를 삭제하므로 이후 invalidateQueries는 무효화할 대상이 없어 no-op이 됩니다.

의도에 따라 둘 중 하나를 선택하세요:

  • 캐시를 완전히 제거하고 재접근 시 fresh fetch를 유도하려면 removeQueries만 사용
  • 기존 데이터를 유지하면서 백그라운드 refetch를 트리거하려면 invalidateQueries만 사용
♻️ removeQueries만 사용하는 경우
  const clearRelatedCache = useCallback(() => {
    queryClient.removeQueries({ queryKey: ['midpoint', id] });
    queryClient.removeQueries({ queryKey: ['recommend', id] });
-
-    queryClient.invalidateQueries({ queryKey: ['midpoint', id] });
  }, [id, queryClient]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/result/`[id]/page.tsx around lines 126 - 145, The clearRelatedCache
function calls queryClient.removeQueries(['midpoint', id]) and then
queryClient.invalidateQueries(['midpoint', id']) which is redundant because
removeQueries deletes the entry; update clearRelatedCache (and any callers like
handleModifyStart and the useEffect cleanup) to use either removeQueries only to
fully drop the cache or replace removeQueries with invalidateQueries only to
keep data and trigger a background refetch—pick the intended behavior and remove
the other call (references: clearRelatedCache, queryClient.removeQueries,
queryClient.invalidateQueries, handleModifyStart, useEffect, id).

114-122: 한글 종성 판별 로직은 정확하지만, 비한글 문자에 대한 방어 코드가 없습니다.

(lastChar - 0xAC00) % 28 연산은 lastChar가 한글 완성형 음절(U+AC00~U+D7A3) 범위에 있을 때만 유효합니다. 카테고리가 숫자나 영문으로 끝나는 경우 잘못된 결과를 반환할 수 있습니다. 현재 카테고리가 항상 한글이라면 큰 문제는 아니지만, 방어적으로 범위 체크를 추가하면 안전합니다.

🛡️ 방어 코드 제안
  const getCategoryText = (category: string | undefined): string => {
    if (!category) return '밍글링 추천 1위';

    const lastChar = category.charCodeAt(category.length - 1);
+   const isKoreanSyllable = lastChar >= 0xAC00 && lastChar <= 0xD7A3;
-   const hasJongseong = (lastChar - 0xac00) % 28 !== 0;
+   const hasJongseong = isKoreanSyllable && (lastChar - 0xAC00) % 28 !== 0;
    return `${category}${hasJongseong ? '이' : '가'} 많은 장소`;
  };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/result/`[id]/page.tsx around lines 114 - 122, The getCategoryText
function uses (lastChar - 0xAC00) % 28 which only makes sense for Hangul
syllables; add a defensive Unicode range check in getCategoryText: compute
lastCharCode from category.charCodeAt(...), verify it is within 0xAC00..0xD7A3
before computing hasJongseong, and if it's outside that range fall back to a
sensible default (e.g., treat as no jongseong so use '가'); update the existing
lastChar/hasJongseong logic inside getCategoryText accordingly to avoid
incorrect results for non-Korean endings.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@app/result/`[id]/page.tsx:
- Line 227: Replace the invalid percentage-based letter-spacing class
tracking-[-1.94%] in the div with a valid unit-based tracking value (e.g.,
tracking-[-1.94px] or tracking-[-0.02em]) so browsers won't ignore it; update
the className on the div in page.tsx (and mirror the same change in
transferModal.tsx where the same tracking-[-1.94%] is used) to use Tailwind
arbitrary unit syntax for letter-spacing with px or em units.

---

Nitpick comments:
In `@app/result/`[id]/page.tsx:
- Around line 147-206: Extract the duplicate subway line→color mapping into a
shared utility (e.g., lib/lineColors.ts or utils/lineColors.ts) and replace the
local implementations: move the logic currently in getLineColor (in page.tsx)
and getLineBadgeStyle (in components/modal/transferModal.tsx) into a single
exported function (e.g., getLineColor or getLineBadgeStyle) and import it in
both files; ensure the function signature matches existing callers (accepting
fullLineName string) and keep the same return values (Tailwind bg- classes) so
callers need only the import change.
- Around line 126-145: The clearRelatedCache function calls
queryClient.removeQueries(['midpoint', id]) and then
queryClient.invalidateQueries(['midpoint', id']) which is redundant because
removeQueries deletes the entry; update clearRelatedCache (and any callers like
handleModifyStart and the useEffect cleanup) to use either removeQueries only to
fully drop the cache or replace removeQueries with invalidateQueries only to
keep data and trigger a background refetch—pick the intended behavior and remove
the other call (references: clearRelatedCache, queryClient.removeQueries,
queryClient.invalidateQueries, handleModifyStart, useEffect, id).
- Around line 114-122: The getCategoryText function uses (lastChar - 0xAC00) %
28 which only makes sense for Hangul syllables; add a defensive Unicode range
check in getCategoryText: compute lastCharCode from category.charCodeAt(...),
verify it is within 0xAC00..0xD7A3 before computing hasJongseong, and if it's
outside that range fall back to a sensible default (e.g., treat as no jongseong
so use '가'); update the existing lastChar/hasJongseong logic inside
getCategoryText accordingly to avoid incorrect results for non-Korean endings.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
app/result/[id]/page.tsx (1)

132-135: handleModifyStart에서 캐시 중복 제거 발생

handleModifyStart에서 clearRelatedCache()를 명시적으로 호출한 뒤, router.replace로 네비게이션하면 컴포넌트가 언마운트되면서 useEffect cleanup의 clearRelatedCache()가 한 번 더 호출됩니다. removeQueries가 멱등(idempotent)이라 에러는 아니지만, 불필요한 중복입니다. useEffect cleanup에 의존하여 여기서는 명시 호출을 제거해도 됩니다.

♻️ 중복 제거 제안
  const handleModifyStart = () => {
-   clearRelatedCache();
    router.replace(`/meeting/${id}`);
  };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/result/`[id]/page.tsx around lines 132 - 135, handleModifyStart currently
calls clearRelatedCache() and then router.replace(`/meeting/${id}`), but because
the component unmount triggered by router.replace will run the useEffect cleanup
that already calls clearRelatedCache(), this causes a redundant duplicate call;
remove the explicit clearRelatedCache() invocation from handleModifyStart so it
only calls router.replace(`/meeting/${id}`) and let the existing useEffect
cleanup handle cache clearing (references: handleModifyStart, clearRelatedCache,
router.replace, the useEffect cleanup that calls clearRelatedCache).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/result/`[id]/page.tsx:
- Around line 137-141: The effect currently calls clearRelatedCache() on mount
and unmount which removes the ['midpoint', id] query and causes an immediate
data drop and refetch; change the useEffect so that on mount it calls
queryClient.invalidateQueries(['midpoint', id]) (or a new helper that calls
invalidateQueries) to trigger a background refetch without clearing existing
data, and keep clearRelatedCache() (which performs removeQueries) only in the
cleanup function so removal happens only on unmount; update the useEffect
surrounding clearRelatedCache, and ensure this aligns with the useMidpoint(id)
subscription.
- Around line 117-121: The current jongseong check using lastChar/hasJongseong
can produce wrong results for non-Hangul characters; update the logic around
category, lastChar and hasJongseong to: obtain the final code point with
category.codePointAt(category.length - 1), check it falls in the Hangul
Syllables range (0xAC00..0xD7AF) before performing (codePoint - 0xAC00) % 28,
and default hasJongseong to false for non-Hangul so the fallback renders '가'
correctly; update the variables lastChar and hasJongseong in this block
accordingly (use codePointAt and an explicit range check).

---

Nitpick comments:
In `@app/result/`[id]/page.tsx:
- Around line 132-135: handleModifyStart currently calls clearRelatedCache() and
then router.replace(`/meeting/${id}`), but because the component unmount
triggered by router.replace will run the useEffect cleanup that already calls
clearRelatedCache(), this causes a redundant duplicate call; remove the explicit
clearRelatedCache() invocation from handleModifyStart so it only calls
router.replace(`/meeting/${id}`) and let the existing useEffect cleanup handle
cache clearing (references: handleModifyStart, clearRelatedCache,
router.replace, the useEffect cleanup that calls clearRelatedCache).

Comment on lines +117 to +121

// 카테고리 종성에 따라 "이/가"를 다르게 렌더링
const lastChar = category.charCodeAt(category.length - 1);
const hasJongseong = (lastChar - 0xac00) % 28 !== 0;
return `${category}${hasJongseong ? '이' : '가'} 많은 장소`;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

한글 종성 판별 시 비한글 문자에 대한 가드 누락

category의 마지막 글자가 한글 음절(U+AC00~U+D7AF) 범위가 아닌 경우(숫자, 영문, 특수문자 등), (lastChar - 0xAC00) % 28 계산이 잘못된 결과를 반환합니다. 예를 들어 카테고리가 "카페2"일 경우 "이"가 잘못 붙을 수 있습니다.

🛡️ 한글 범위 체크 추가 제안
     const lastChar = category.charCodeAt(category.length - 1);
-    const hasJongseong = (lastChar - 0xac00) % 28 !== 0;
+    const isKoreanSyllable = lastChar >= 0xac00 && lastChar <= 0xd7af;
+    const hasJongseong = isKoreanSyllable && (lastChar - 0xac00) % 28 !== 0;
     return `${category}${hasJongseong ? '이' : '가'} 많은 장소`;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// 카테고리 종성에 따라 "이/가"를 다르게 렌더링
const lastChar = category.charCodeAt(category.length - 1);
const hasJongseong = (lastChar - 0xac00) % 28 !== 0;
return `${category}${hasJongseong ? '이' : '가'} 많은 장소`;
// 카테고리 종성에 따라 "이/가"를 다르게 렌더링
const lastChar = category.charCodeAt(category.length - 1);
const isKoreanSyllable = lastChar >= 0xac00 && lastChar <= 0xd7af;
const hasJongseong = isKoreanSyllable && (lastChar - 0xac00) % 28 !== 0;
return `${category}${hasJongseong ? '이' : '가'} 많은 장소`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/result/`[id]/page.tsx around lines 117 - 121, The current jongseong check
using lastChar/hasJongseong can produce wrong results for non-Hangul characters;
update the logic around category, lastChar and hasJongseong to: obtain the final
code point with category.codePointAt(category.length - 1), check it falls in the
Hangul Syllables range (0xAC00..0xD7AF) before performing (codePoint - 0xAC00) %
28, and default hasJongseong to false for non-Hangul so the fallback renders '가'
correctly; update the variables lastChar and hasJongseong in this block
accordingly (use codePointAt and an explicit range check).

Comment on lines +137 to +141
useEffect(() => {
clearRelatedCache();

return () => clearRelatedCache();
}, [clearRelatedCache]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

마운트 시 removeQueries가 현재 컴포넌트의 데이터를 제거하여 불필요한 리패치 및 로딩 깜빡임 발생

clearRelatedCache가 마운트 시점에도 호출되면서 ['midpoint', id] 쿼리 데이터를 제거합니다. 이 컴포넌트가 useMidpoint(id)로 같은 쿼리를 구독 중이므로, 마운트 직후 데이터가 사라지고 → 로딩 상태 전환 → 리패치가 발생합니다. 정상적인 네비게이션(최초 진입)에서도 불필요한 리패치와 로딩 UI 깜빡임이 생깁니다.

뒤로가기 시 캐시 무효화가 목적이라면, 언마운트 시에만 캐시를 제거하면 충분합니다. 마운트 시에는 invalidateQueries를 사용하면 기존 데이터를 보여주면서 백그라운드 리패치가 가능합니다.

🔧 수정 제안: 마운트 시 invalidate, 언마운트 시 remove
  useEffect(() => {
-   clearRelatedCache();
-
-   return () => clearRelatedCache();
- }, [clearRelatedCache]);
+   // 마운트 시에는 백그라운드 리패치 (기존 데이터 유지)
+   queryClient.invalidateQueries({ queryKey: ['midpoint', id] });
+   queryClient.invalidateQueries({ queryKey: ['recommend', id] });
+
+   // 언마운트 시에는 캐시 완전 제거 (뒤로가기 캐시 무효화)
+   return () => {
+     queryClient.removeQueries({ queryKey: ['midpoint', id] });
+     queryClient.removeQueries({ queryKey: ['recommend', id] });
+   };
+ }, [id, queryClient]);

또는 마운트 시 캐시 무효화가 아예 필요 없다면 언마운트 cleanup만 남기세요:

useEffect(() => {
  return () => clearRelatedCache();
}, [clearRelatedCache]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/result/`[id]/page.tsx around lines 137 - 141, The effect currently calls
clearRelatedCache() on mount and unmount which removes the ['midpoint', id]
query and causes an immediate data drop and refetch; change the useEffect so
that on mount it calls queryClient.invalidateQueries(['midpoint', id]) (or a new
helper that calls invalidateQueries) to trigger a background refetch without
clearing existing data, and keep clearRelatedCache() (which performs
removeQueries) only in the cleanup function so removal happens only on unmount;
update the useEffect surrounding clearRelatedCache, and ensure this aligns with
the useMidpoint(id) subscription.

@kangdy25 kangdy25 merged commit 0e0550b into main Feb 18, 2026
4 checks passed
@kangdy25 kangdy25 deleted the refactor/prevent-back-navigation branch February 19, 2026 04:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants